import os
import re
import socket
import time
from concurrent.futures import ThreadPoolExecutor
from struct import unpack
from urllib.parse import urlparse

import av
import cv2
import redis

from auth import DigestAuth
from nal_unit import NalUnit
from rtp_datagram import RTPDatagram

get_now_milli_time = lambda: int(time.time() * 1000)
get_now_milli = lambda: int(time.time())

m_Vars = {
    "bufLen": 1024 * 50,
    # "defaultUserName": "admin",     # RTSP用户名
    # "defaultPasswd": "wanji123",     # RTSP用户名对应密码
    # "defaultServerIp": "192.168.2.101",  # RTSP服务器IP地址
    # "defaultServerPort": 554,           # RTSP服务器使用端口
    # "defaultTestUrl": "rtsp://192.168.2.101:554",
    # "LicenceUrl": "rtsp://admin:wanji123@192.168.2.101:554",
    "defaultUserAgent": "LibVLC/3.0.8 (LIVE555 Streaming Media v2016.11.28)"
    # "LibVLC/2.0.3 (LIVE555 Streaming Media v2011.12.23)"
}


class RTSPClientError(Exception):
    pass


class RTSPClientRetryError(RTSPClientError):
    pass


class RTSPClientFatalError(RTSPClientError):
    pass


class GetRtspData:
    def response1(self, method):
        auth = DigestAuth(self.username, self.password, self._realm,
                          self._nonce, method.upper(),
                          uri=self.LicenceUrl)
        responses = auth.header
        print(responses)
        return responses

    def genmsg_OPTIONS(self, userAgent):
        msgRet = "OPTIONS " + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "\r\n"
        return msgRet

    def genmsg_OPTIONS2(self, userAgent):
        method = "OPTIONS "
        respon = self.response1("OPTIONS")
        msgRet = method + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += 'Authorization:'
        if self.username:
            msgRet += 'Digest username=\"' + self.username + '\"'
        else:
            msgRet += 'Digest username=\"''\"'
        if self._realm:
            msgRet += ', realm=\"' + self._realm + '\"'
        else:
            msgRet += ', realm=\"''\"'
        if self._nonce:
            msgRet += ', nonce=\"' + self._nonce + '\"'
        else:
            msgRet += ', nonce=\"''\"'
        msgRet += ', uri=\"' + self.LicenceUrl + '\"'
        msgRet += ', response=\"' + respon + "\"\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "\r\n"
        print(msgRet)
        return msgRet

    def genmsg_DESCRIBE(self, userAgent):
        msgRet = "DESCRIBE " + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "Accept: application/sdp\r\n"
        msgRet += "\r\n"
        return msgRet

    def genmsg_DESCRIBE2(self, userAgent):

        respon = self.response1("DESCRIBE")
        msgRet = "DESCRIBE " + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "Accept: application/sdp\r\n"
        msgRet += 'Authorization:'
        if self.username:
            msgRet += 'Digest username=\"' + self.username + '\"'
        else:
            msgRet += 'Digest username=\"''\"'
        if self._realm:
            msgRet += ', realm=\"' + self._realm + '\"'
        else:
            msgRet += ', realm=\"''\"'
        if self._nonce:
            msgRet += ', nonce=\"' + self._nonce + '\"'
        else:
            msgRet += ', nonce=\"''\"'
        msgRet += ', uri=\"' + self.LicenceUrl + '\"'
        msgRet += ', response=\"' + respon + "\"\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "\r\n"
        print(msgRet)
        return msgRet

    def genmsg_SETUP(self, userAgent):
        msgRet = "SETUP " + self.LicenceUrl + "/trackID=0" + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "Transport: RTP/AVP/TCP;unicast;interleaved=0-1\r\n"
        msgRet += "\r\n"
        return msgRet

    def genmsg_SETUP2(self, userAgent):
        msgRet = "SETUP " + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "Transport: RTP/AVP/TCP;unicast;interleaved=2-3\r\n"
        msgRet += "Session: " + str(self._session) + "\r\n"
        msgRet += "\r\n"
        return msgRet

    def genmsg_SETUP3(self, userAgent):

        respon = self.response1("SETUP")
        msgRet = "SETUP " + self.LicenceUrl + "/trackID=1 RTSP/1.0\r\n"
        msgRet += "Transport: RTP/AVP/TCP;unicast;interleaved=0-1\r\n"
        # msgRet += "Transport: RTP/AVP/UDP;unicast;client_port=31548-31549\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        # msgRet += "User-Agent: " + userAgent + "\r\n"
        # msgRet += "Accept: application/sdp\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += 'Authorization:'
        if self.username:
            msgRet += 'Digest username=\"' + self.username + '\"'
        else:
            msgRet += 'Digest username=\"''\"'
        if self._realm:
            msgRet += ', realm=\"' + self._realm + '\"'
        else:
            msgRet += ', realm=\"''\"'
        if self._nonce:
            msgRet += ', nonce=\"' + self._nonce + '\"'
        else:
            msgRet += ', nonce=\"''\"'
        msgRet += ', uri=\"' + self.LicenceUrl + '\"'
        msgRet += ', response=\"' + respon + "\"\r\n"
        msgRet += "\r\n"
        print(msgRet)
        return msgRet

    def genmsg_SETUP4(self, userAgent):

        respon = self.response1("SETUP")
        msgRet = "SETUP " + self.LicenceUrl + "/trackID=2 RTSP/1.0\r\n"
        msgRet += "Transport: RTP/AVP/TCP;unicast;interleaved=2-3\r\n"
        # msgRet += "Transport: RTP/AVP/UDP;unicast;client_port=31548-31549\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        # msgRet += "User-Agent: " + userAgent + "\r\n"
        # msgRet += "Accept: application/sdp\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += 'Authorization:'
        if self.username:
            msgRet += 'Digest username=\"' + self.username + '\"'
        else:
            msgRet += 'Digest username=\"''\"'
        if self._realm:
            msgRet += ', realm=\"' + self._realm + '\"'
        else:
            msgRet += ', realm=\"''\"'
        if self._nonce:
            msgRet += ', nonce=\"' + self._nonce + '\"'
        else:
            msgRet += ', nonce=\"''\"'
        msgRet += ', uri=\"' + self.LicenceUrl + '\"'
        msgRet += ', response=\"' + respon + "\"\r\n"
        msgRet += "\r\n"
        print(msgRet)
        return msgRet

    def genmsg_PLAY(self, userAgent):
        respon = self.response1("PLAY")
        msgRet = "PLAY " + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += 'Authorization:'
        if self.username:
            msgRet += 'Digest username=\"' + self.username + '\"'
        else:
            msgRet += 'Digest username=\"''\"'
        if self._realm:
            msgRet += ', realm=\"' + self._realm + '\"'
        else:
            msgRet += ', realm=\"''\"'
        if self._nonce:
            msgRet += ', nonce=\"' + self._nonce + '\"'
        else:
            msgRet += ', nonce=\"''\"'
        msgRet += ', uri=\"' + self.LicenceUrl + '\"'
        msgRet += ', response=\"' + respon + "\"\r\n"
        msgRet += "Session: " + self._session + "\r\n"
        msgRet += "Range: npt=0.000-\r\n"
        msgRet += "\r\n"
        return msgRet

    def genmsg_TEARDOWN(self, userAgent):
        msgRet = "TEARDOWN " + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "Session: " + self._session + "\r\n"
        msgRet += "\r\n"
        return msgRet

    def decodeMsg(strContent):
        mapRetInf = {}
        for str in [elem for elem in strContent.split("\n") if len(elem) > 1][
                   2:-1]:
            print(str)
            tmp2 = str.split(":")
            mapRetInf[tmp2[0]] = tmp2[1][:-1]
            print(mapRetInf)
        return mapRetInf

    def _parse_digest_auth_header(self, header):
        print('head-----------', header)
        try:
            self._realm = re.search(r'realm=\"([^\"]+)\"', str(header)).group(1)
            self._nonce = re.search(r'nonce=\"([\w]+)\"', str(header)).group(1)
        except:
            pass

    def SendHeart(self, socktp, userAgent):
        msgRet = "GET_PARAMETER " + self.LicenceUrl + " RTSP/1.0\r\n"
        msgRet += "CSeq: " + str(self._cseq) + "\r\n"
        msgRet += "User-Agent: " + userAgent + "\r\n"
        msgRet += "Session: " + self._session + "\r\n"
        msgRet += "\r\n"
        socktp.send(bytes(msgRet, 'utf-8'))

    @property
    def url(self):
        return self.__url

    @url.setter
    def url(self, url):
        parsed = urlparse(url)
        if parsed.scheme != "rtsp":
            raise RTSPClientFatalError(
                f'Protocol mismatch: expecting "rtsp", got "{parsed.scheme}"')
        try:
            self.host = parsed.hostname  # '192.168.3.64'
            self.ip = socket.gethostbyname(self.host)
        # print(self.host)
        # print(self.ip)
        except:
            raise RTSPClientFatalError(
                f'Failed to resolve {parsed.hostname} to IP address')

        if parsed.username is not None:
            print('--------')
            self.username = parsed.username
        if parsed.username is not None:
            self.password = parsed.password
        if parsed.username is not None:
            self.port = parsed.port
        if len(parsed.path) > 0 or len(parsed.query) > 0:
            self.path = parsed.path  # + '?' + parsed.query
        else:
            self.path = ''
        if self.username:
            self.LicenceUrl = f'rtsp://{self.host}:{self.port}{self.path}'
        else:
            self.LicenceUrl = url
        self.__url = url
        print('self url', self.LicenceUrl)

    def ConnectCamera(self):
        # 连接相机(socket.AF_INET, socket.SOCK_STREAM)
        self._socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        # self._socket.bind(('192.168.3.246', 31549))
        # self._socket.
        self._socket.connect((self.ip, self.port))
        self._cseq = 1

    def options(self):
        # print(genmsg_OPTIONS(m_Vars["defaultTestUrl"], seq, m_Vars["defaultUserAgent"]))
        print('options--------1', self.genmsg_OPTIONS(m_Vars["defaultUserAgent"]))
        sends = self._socket.send(
            bytes(self.genmsg_OPTIONS(m_Vars["defaultUserAgent"]), 'utf-8'))
        print("genmsg_OPTIONS Send:" + str(sends))
        data = self._socket.recv(m_Vars["bufLen"])
        # self._parse_digest_auth_header(data)
        self._cseq = self._cseq + 1
        print('options--------2')
        # sends = self._socket.send(
        #     bytes(self.genmsg_OPTIONS2(m_Vars["defaultUserAgent"]), 'utf-8'))
        # print("genmsg_OPTIONS2 Send:" + str(sends))
        # data = self._socket.recv(m_Vars["bufLen"])
        # self._cseq = self._cseq + 1
        print('options--------3')

    def describe(self):
        print('describe-----------1')
        self._socket.send(
            bytes(self.genmsg_DESCRIBE(m_Vars["defaultUserAgent"]), 'utf-8'))
        msg1 = self._socket.recv(m_Vars["bufLen"])
        # print(str(msg1))
        self._parse_digest_auth_header(msg1)
        self._cseq = self._cseq + 1
        print('describe-----------2')
        sends = self._socket.send(
            bytes(self.genmsg_DESCRIBE2(m_Vars["defaultUserAgent"]), 'utf-8'))
        print("genmsg_DESCRIBE2 Send:" + str(sends))
        data = self._socket.recv(m_Vars["bufLen"])
        self._cseq = self._cseq + 1

    def setup(self):
        print('setup-----------1')

        self._socket.send(
            bytes(self.genmsg_SETUP3(m_Vars["defaultUserAgent"]), 'utf-8'))
        msg1 = self._socket.recv(m_Vars["bufLen"])
        self._cseq = self._cseq + 1
        recv_msg1 = msg1.decode()
        session_pos = recv_msg1.find('Session')
        session_value_begin_pos = recv_msg1.find(' ', session_pos + 8) + 1
        session_value_end_pos = recv_msg1.find(';', session_pos + 8)
        if session_value_end_pos == -1:
            session_value_end_pos = len(recv_msg1)

        self._session = recv_msg1[session_value_begin_pos:session_value_end_pos]
        self._RecvRtspLen = len(self._session) + 39
        print('setup-----------2')
        self._socket.send(
            bytes(self.genmsg_SETUP4(m_Vars["defaultUserAgent"]), 'utf-8'))
        msg1 = self._socket.recv(m_Vars["bufLen"])
        self._cseq = self._cseq + 1

    def play(self):
        print('play-----------1')

        self._socket.send(
            bytes(self.genmsg_PLAY(m_Vars["defaultUserAgent"]), 'utf-8'))
        # msg1 = self._socket.recv(m_Vars["bufLen"])
        # print(msg1)
        self._socket.settimeout(5)
        self._cseq = self._cseq + 1
        print('play-----------2')

    def _close(self):
        # self._socket.send(bytes(self.genmsg_TEARDOWN(m_Vars["defaultUserAgent"]), 'utf-8'))
        if self._socket is not None:
            self._socket.close()

    def __enter__(self):
        return self

    def __exit__(self, exc_t, exc_v, traceback):
        # self._socket.send(bytes(self.genmsg_TEARDOWN(m_Vars["defaultUserAgent"]), 'utf-8'))
        self._close()

    def __del__(self):
        self._close()

    def StartPlay(self, pool):
        self.ConnectCamera()
        self.options()
        self.describe()
        self.setup()
        self.play()
        # logger.info("建立连接成功")
        # print("建立连接成功")
        i = 0
        # pool = redis.ConnectionPool(host='127.0.0.1', port=6379, db=10, decode_responses=False)
        now_time_sort = 0
        now_index = 0

        while True:
            try:
                # s.send(genmsg_ANNOUNCE(m_Vars["defaultServerIp"]))
                msg_recv = self._socket.recv(4)
                if 4 > len(msg_recv):
                    msg_recv += self._socket.recv(4 - len(msg_recv))
                if len(msg_recv) == 0:
                    continue
                # 获取RTP_HEADER
                TcpH_magic = unpack('!B', msg_recv[:1])[0]
                TcpH_channel = unpack('!B', msg_recv[1:2])[0]
                TcpH_length = unpack('!B', msg_recv[2:3])[0] << 8 | unpack('!B', msg_recv[3:4])[0]
                if TcpH_magic == 0x24:
                    DataBuff = self._socket.recv(TcpH_length)
                    # print(DataBuff)
                    if TcpH_length > len(DataBuff):
                        DataBuff += self._socket.recv(TcpH_length - len(DataBuff))
                    if len(DataBuff[1:2]):
                        RtpOrRtcp = unpack('!B', DataBuff[1:2])[0]
                        RtpOrRtcp = RtpOrRtcp & 0b01100000
                    else:
                        continue
                    # 区分RTP协议
                    if DataBuff and RtpOrRtcp == 96:
                        # RTP包
                        rtp_data = RTPDatagram(DataBuff)
                        # 获得未解析的payload
                        nal_payload_temp = rtp_data.payload
                        # 通过NALU获得解析后的H264数据
                        nal_parse = NalUnit(nal_payload_temp)
                        if nal_parse.forbidden:
                            continue
                        # 判断当前是否为结尾
                        if nal_parse.fragment_end == 0:
                            self.nal_payload = self.nal_payload + nal_parse.payload
                            continue
                        elif nal_parse.fragment_end == 1:
                            # print("2@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@")
                            # 当前为帧结尾
                            s_data = rtp_data.s_data
                            ms_data = rtp_data.ms_data
                            # 如果RTSP流中没有时间信息（即非定制相机） 则使用系统的时间戳
                            if rtp_data.s_data == 0:
                                s_data = int(time.time())
                                ms_data = int(str(int(round(time.time() * 1000)))[10:13])
                            else:
                                s_data = rtp_data.s_data
                                ms_data = rtp_data.ms_data
                            RTP_time = str(s_data) + "" + str(ms_data)
                            if ms_data < 10:
                                RTP_time = str(s_data) + "00" + str(ms_data)
                            elif ms_data < 100:
                                RTP_time = str(s_data) + "0" + str(ms_data)

                            RTP_Seconds = RTP_time[0:10]
                            RTP_Milli_Seconds = RTP_time[10:13]
                            if (len(RTP_Milli_Seconds) < 3):
                                print("---------时间戳异常---------")

                            RTP_time = RTP_time[0:10] + '.' + RTP_time[10:13]

                            self.nal_payload = self.nal_payload + nal_parse.payload

                            str_camera_id = str(self.camera_id)

                            # 如果RTSP流中没有时间信息（即非定制相机） 则使用系统的时间戳 （- 2208988800 或者 - 2208988800000 是为了时区换算）
                            if rtp_data.s_data == 0:
                                key1 = str_camera_id + '_' + str(int(RTP_Seconds))
                            else:
                                key1 = str_camera_id + '_' + str(int(RTP_Seconds) - 2208988800)

                            var = get_now_milli_time()
                            if rtp_data.s_data == 0:
                                NTPtime = (int(RTP_Seconds) * 1000 + int(RTP_Milli_Seconds))
                            else:
                                NTPtime = (int(RTP_Seconds) * 1000 + int(RTP_Milli_Seconds)) - 2208988800000

                            # now_time = int(str(NTPtime) + str(var)[10:13])

                            if now_time_sort == 0:
                                now_time_sort = NTPtime
                                now_time = int(str(now_time_sort) + '0')
                            else:
                                if now_time_sort == NTPtime:
                                    now_index = now_index + 1
                                    now_time = int(str(NTPtime) + str(now_index))
                                    now_time_sort = NTPtime
                                else:
                                    now_index = 0
                                    now_time_sort = NTPtime
                                    now_time = int(str(NTPtime) + '0')

                            # RTP_time = str(s_data) + "" + str(ms_data)
                            # if ms_data < 10:
                            #     RTP_time = str(s_data) + "00" + str(ms_data)
                            # elif ms_data < 100:
                            #     RTP_time = str(s_data) + "0" + str(ms_data)
                            # RTP_time = RTP_time[0:10] + '.' + RTP_time[10:13]
                            self.nal_payload = self.nal_payload + nal_parse.payload
                            packets = self.codec.parse(self.nal_payload)
                            # print("Parsed {} packets from {} bytes:".format(len(packets), len(self.nal_payload)))
                            if len(packets) > 2:
                                break

                            r = redis.Redis(connection_pool=pool)

                            str_camera_id = str(self.camera_id)
                            # key1 = str_camera_id + '_' + str(get_now_milli())
                            # now_time = get_now_milli_time()
                            r.zadd(key1, {self.nal_payload: now_time})
                            r.expire(key1, self.retained_time)

                            # r.set(str_camera_id, str(now_time))
                            # 如果RTSP流中没有时间信息（更新redis相机号最新时间）
                            if rtp_data.s_data == 0:
                                r.set(str_camera_id, str(int(RTP_Seconds)))
                            else:
                                r.set(str_camera_id, str(int(RTP_Seconds) - 2208988800))

                            self.nal_payload = b''
                            i = i + 1
                            if i % 10 == 0:
                                self.SendHeart(self._socket, m_Vars["defaultUserAgent"])
                    else:
                        # 非RTP包不进行处理
                        continue
                else:
                    # 丢弃非rtp包
                    data = self._socket.recv(self._RecvRtspLen - 4)
                    # print(data)
            except socket.error as e:
                # # 发生网络异常
                # logging.basicConfig(level=logging.DEBUG,  # 控制台打印的日志级别
                #                     filename='new.log',
                #                     filemode='a',  ##模式，有w和a，w就是写模式，每次都会重新写日志，覆盖之前的日志
                #                     # a是追加模式，默认如果不写的话，就是追加模式
                #                     format=
                #                     '%(asctime)s - %(pathname)s[line:%(lineno)d] - %(levelname)s: %(message)s'
                #                     # 日志格式
                #                     )
                time.sleep(3)
                MyLog.writeLog("{}[:{}] - except video recv err! {}"
                               .format(__file__.split('/')[len(__file__.split('/')) - 1],
                                       sys._getframe().f_lineno, e), LOG_INFO, ENABLE_WRITE_LOG, ENABLE_PRINT)
                # print("video recv err!\n", e)
                return
                # self.StartPlay()

    def analysis_img(self, camera_id, _time_start, _time_end, save_path, pool):

        other_style_time = str(camera_id) + '_' + str(_time_start) + '_' + str(_time_end)
        i = 0
        count = 0
        success = 0

        # for _time in range(_time_start - 2, _time_start):
        #
        #     key = str(camera_id) + '_' + str(_time)
        #     r = redis.Redis(connection_pool=pool)
        #     var = r.zrange(key, 0, -1, withscores=True)
        #
        #     for value in var:
        #         payload = value[0]
        #         file_name = value[1]
        #
        #         packets = self.codec.parse(payload)
        #         if len(packets) > 2:
        #             continue
        #
        #         for packet in packets:
        #             try:
        #                 frames = self.codec.decode(packet)
        #             except Exception as e:
        #                 print(e)

        img_path = save_path + '/camera{}'.format(other_style_time)

        img_paths = []
        for _time in range(_time_start, _time_end):

            key = str(camera_id) + '_' + str(_time)
            # print('key:', key)
            r = redis.Redis(connection_pool=pool)
            var = r.zrange(key, 0, -1, withscores=True)

            print('data count:', len(var))

            for value in var:
                i = i + 1
                count = count + 1
                payload = value[0]
                file_name = value[1]
                packets = self.codec.parse(payload)
                # packets = self.codec.parse(None)
                if len(packets) > 2:
                    continue
                for packet in packets:
                    # print(count, ' 找到了有数据的包 ', key, i)
                    i = 0

                    try:
                        frames = self.codec.decode(packet)
                        for frame in frames:
                            img_data = frame.to_ndarray(format='bgr24')
                            if len(img_data) > 0:

                                if not os.path.exists(img_path):
                                    os.mkdir(img_path)

                                img = img_path + '/{}.jpg'.format(file_name)
                                img_paths.append(img)
                                cv2.imwrite(img, img_data)
                                print(img)
                                success = success + 1
                    except Exception as e:
                        print(e)

        # print('相机id：', camera_id, "总数据条数：", count, "解析成功数：", success, "失败数：", (count - success))
        # print(img_paths)
        print('Run Result:', camera_id, '{', ','.join(img_paths), '}')

    def analysis_img3(self, camera_id, _time_start, _time_end, save_path, pool, threadDefaultWorker):
        start_time = time.time()
        other_style_time = str(camera_id) + '_' + str(_time_start) + '_' + str(_time_end)
        i = 0
        count = 0
        success = 0
        thread_save_pool = ThreadPoolExecutor(max_workers=threadDefaultWorker)
        for _time in range(_time_start - 2, _time_start):

            key = str(camera_id) + '_' + str(_time)
            r = redis.Redis(connection_pool=pool)
            var = r.zrange(key, 0, -1, withscores=True)

            for value in var:
                payload = value[0]
                file_name = value[1]

                packets = self.codec.parse(payload)
                if len(packets) > 2:
                    continue

                for packet in packets:
                    try:
                        frames = self.codec.decode(packet)
                    except Exception as e:
                        print(e)

        img_path = save_path + '/camera{}'.format(other_style_time)

        img_paths = []
        time_out = 0
        for _time in range(_time_start, _time_end):
            get_redis_time = time.time()
            key = str(camera_id) + '_' + str(_time)
            # print('key:', key)
            r = redis.Redis(connection_pool=pool)
            var = r.zrange(key, 0, -1, withscores=True)
            get_redis_time_end = time.time()
            time_out = time_out + (get_redis_time_end - get_redis_time)
            print('data count:', len(var))
            self.logger.info("find_key" + str(_time))
            for value in var:
                i = i + 1
                count = count + 1
                payload = value[0]
                file_name = value[1]
                packets = self.codec.parse(payload)
                if len(packets) > 2:
                    continue
                for packet in packets:
                    # print(count, ' 找到了有数据的包 ', key, i)
                    i = 0

                    try:
                        frames = self.codec.decode(packet)
                        for frame in frames:
                            img_data = frame.to_ndarray(format='bgr24')
                            if len(img_data) > 0:

                                if not os.path.exists(img_path):
                                    os.mkdir(img_path)

                                img = img_path + '/{}.jpg'.format(file_name)
                                img_paths.append(img)
                                # cv2.imwrite(img, img_data)
                                thread_save_pool.submit(self.save_image, img, img_data)
                                print(img)
                                success = success + 1
                    except Exception as e:
                        print(e)

        end_time = time.time()
        print("从redis中读取到内存耗时：" + str(time_out))
        print("从内存写到文件耗时：" + str(end_time - start_time - time_out))
        print("系统总耗时：" + str(end_time - start_time))
        # print('Run Result:', camera_id, '{', ','.join(img_paths), '}')
        print('Run Result:', camera_id, '{', ','.join(img_paths), '}')
        self.logger.info('Run Result:' + str(camera_id) + '{'+ ','.join(img_paths) + '}')
        # self.logger.info("总数据条数：" + str(count) + "解析成功数：" + str(success) + "失败数：" + str(count - success))

    def analysis_img4(self, camera_id, _time_start, timeStart, _time_end, timeEnd, save_path, pool,
                      threadStartEndWorker):
        start_time = time.time()
        thread_save_pool = ThreadPoolExecutor(max_workers=threadStartEndWorker)
        other_style_time = str(camera_id) + '_' + str(_time_start) + '_' + str(_time_end - 1)
        i = 0
        count = 0
        success = 0

        for _time in range(_time_start - 2, _time_start):

            key = str(camera_id) + '_' + str(_time)
            r = redis.Redis(connection_pool=pool)
            var = r.zrange(key, 0, -1, withscores=True)

            for value in var:
                payload = value[0]
                file_name = value[1]

                packets = self.codec.parse(payload)
                if len(packets) > 2:
                    continue

                for packet in packets:
                    try:
                        frames = self.codec.decode(packet)
                    except Exception as e:
                        print(e)

        img_path = save_path + '/camera{}'.format(other_style_time)

        img_paths = []
        j = 0
        time_out = 0
        for _time in range(_time_start, _time_end):
            get_redis_time = time.time()
            key = str(camera_id) + '_' + str(_time)
            # print('key:', key)
            r = redis.Redis(connection_pool=pool)
            var = r.zrange(key, 0, -1, withscores=True)
            get_redis_time_end = time.time()
            time_out = time_out + (get_redis_time_end - get_redis_time)
            # print('data count:', len(var))

            for value in var:
                i = i + 1
                count = count + 1
                payload = value[0]
                file_name = value[1]
                packets = self.codec.parse(payload)
                # packets = self.codec.parse(None)
                if len(packets) > 2:
                    continue
                for packet in packets:
                    # print(count, ' 找到了有数据的包 ', key, i)
                    i = 0

                    try:
                        frames = self.codec.decode(packet)
                        for frame in frames:
                            img_data = frame.to_ndarray(format='bgr24')
                            if len(img_data) > 0:
                                print(timeStart, ' 时间比对 ', str(file_name)[0:13], '结束时间 ', timeEnd)
                                if not os.path.exists(img_path):
                                    os.mkdir(img_path)

                                if int(timeStart) <= int(str(file_name)[0:13]) <= int(timeEnd):
                                    # img = img_path + '/{}.jpg'.format(file_name)
                                    j = j + 1
                                    img = img_path + '/' + str(j) + '.jpg'
                                    img_paths.append(img)
                                    # cv2.imwrite(img, img_data)
                                    thread_save_pool.submit(self.save_image, img, img_data)
                                    # print(img)
                                    success = success + 1


                    except Exception as e:
                        print(e)

        end_time = time.time()
        print("从redis中读取到内存耗时：" + str(time_out))
        print("从内存写到文件耗时：" + str(end_time - start_time - time_out))
        print("系统总耗时：" + str(end_time - start_time))
        # print('Run Result:', camera_id, '{', ','.join(img_paths), '}')
        print('Run Result:', camera_id, '{', ','.join(img_paths), '}')
        self.logger.info('Run Result:' + str(camera_id) + '{' + ','.join(img_paths) + '}')

    def save_image(self, img, img_data):
        cv2.imwrite(img, img_data)
        print(img)

    def __init__(self, url, camera_id, retained_time, logger):
        self.codec = av.CodecContext.create('h264', 'r')
        # 解析url
        self.username = None
        self.password = None
        self.host = None
        self.ip = None
        self.port = 554
        # self.path = None
        self.path = ''
        self.LicenceUrl = ''
        # self.safe_url = None
        self.url = url
        self._cseq = 0
        self._socket = None
        self._session = None
        self._realm = None
        self._nonce = None
        self._auth = None
        self._auth_attempts = 0
        self.nal_payload = b''
        self.camera_id = camera_id
        self.retained_time = retained_time
        self.logger = logger
